#ifndef __CAN_H
#define __CAN_H

#include <queue>
#include "datatypes.h"

#ifndef PF_CAN
#define PF_CAN 29
#endif

#define	CAN_RAW	1

#define CAN_EFF_FLAG	0x80000000u
#define	CAN_RTR_FLAG	0x40000000u
#define CAN_ERR_FLAG	0x20000000u

#define	CAN_EFF_MASK	0x1FFFFFFFu
using namespace std;

namespace Imx
{
	struct can_frame
	{
		u32	can_id;
		u8	can_dlc;
		u8	data[8]__attribute__((aligned(8)));
	};

	struct sockaddr_can
	{
		u16	can_family;
		s32	can_ifindex;
		union
		{ 
			struct
			{
				u32 rx_id;
				u32 tx_id;
			} tp;
		} can_addr;
	};

	class Can : public IceUtil::Monitor<IceUtil::Mutex>
	{   
		s32 _cSock;
		s32 _wSock;
		bool _head;	// 是否接收到头部
		bool _tail;	// 
		bool _listen;	// 监听状态
		//bool _externalSource; // 控制是否使用外部数据源
		struct can_frame _dFrame;
		struct sockaddr_can _cAddr;
		queue<struct can_frame> _recvQueue;	// 数据接收队列

		queue<struct can_frame>	_setAckQueue; // 配置指令应答消息处理队列
	public:
		Can();
		~Can();
		struct can_frame popFrame();
		void pushFrame(struct can_frame frame);
		void init();
		void listen();
		void detectNotify();
		void dataNotify();
		void finishNotify(u8 devId, u8 chnNo);
		void stepNotify(u8 devId, u8 chnNo, Step ss);

		void setNotify(TaskProtect tp);
		void setPutAck(struct can_frame frame);
		s32 setWaitAck(u32 *can_id, s32 timeout);

		void send(u8 *, u8);
		void ack(u8, u8);

		void setExternalSource(bool);
		bool isExternalSource();
	};
}
// 应答类型
#define	ACK_OK	0x01	// 接收正确
#define	ACK_RE	0x02	// 接收错误需要重新传输

#define	PKT_ID_MASK		0x000000FFu	// [7:0]
#define	PKT_CHN_MASK	0x00000700u	// [10:8]
#define	PKT_LEN_MASK	0x0001F800u	// [16:11]	
#define	PKT_TYPE_MASK	0x00060000u	// [18:17]
#define	RESERVED1		0x00080000u	// [19]
#define PKT_CMD_MASK	0x03F00000u	// [25:20]
#define RESERVED2		0x1C000000u	// [28:26]
#define	EFF				0xE0000000u	// [31:29]

#define CHN_1			0x00000000u
#define CHN_2			0x00000100u
#define CHN_3			0x00000200u
#define CHN_4			0x00000300u


// 传输类型
#define	TYPE_OFFSET		17
#define	TYPE_HEAD		0x00040000u
#define TYPE_BODY		0x00000000u
#define	TYPE_TAIL		0x00020000u
#define	TYPE_SINGLE		0x00060000u



// 消息类型
#define	MCMD			0x00000000u
#define	MCMD_HB			0x00100000u		// 心跳请求通知	(1)	中位机定时
#define	MCMD_DATA		0x00200000u		// 数据请求通知	(1)	中位机定时
#define	MCMD_SET		0x00300000u		// 配置请求通知	(1)	中位机主动
#define	MCMD_STEP		0x00400000u		// 工步下发通知	(1)	中位机主动
#define	MCMD_CORR		0x00500000u		// 矫正系数通知	data[0]~data[3] 32 bit :	CORR_TYPE	[7:0]	
#define	MCMD_FIN		0x00600000u		// 结束指令

//	MCMD_CORR 子类定义


#define DCMD			0x01000000u		
#define	DCMD_HB_ACK		0x01100000u		// 心跳应答	(1)
#define	DCMD_DATA_ACK	0x01200000u		// 数据应答	(3) 20bytes data + 2bytes crc
#define	DCMD_SET_ACK	0x01300000u		// 配置应答	(1)
#define	DCMD_STEP_ACK	0x01400000u		// 工步应答
#define	DCMD_CORR_ACK	0x01500000u		// 矫正应答
#define	DCMD_FIN_ACK	0x01600000u		// 结束应答

#define DCMD_NOTIFY		0x01F00000u		// 事件上报	 下位机主动通知



#endif
